package hh.util.type;

import hh.util.Asserts;
import hh.util.CommonUtil;
import hh.util.coll.CollUtil;
import hh.util.time.TimeUtil;

import java.util.*;

public class TypeUtil {

    static final String parserErr = "无法将{}解析为{}";

    private static final List<Class> baseTypes = CollUtil.immutableList(
            byte.class, short.class, int.class, long.class, float.class, double.class, char.class, boolean.class);

    private static final List<Class> packageTypes = CollUtil.immutableList(
            Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Character.class, Boolean.class);

    public static final Map<Class, TypeParser> userSelfDefineParser = new HashMap<>();
    private static final Map<Class, TypeParser> typeToParser = Collections.unmodifiableMap(
            new HashMap<Class, TypeParser>() {{
                put(byte.class, TypeUtil::parseByte);
                put(Byte.class, TypeUtil::parseByte);
                put(short.class, TypeUtil::parseShort);
                put(Short.class, TypeUtil::parseShort);
                put(int.class, TypeUtil::parseInteger);
                put(Integer.class, TypeUtil::parseInteger);
                put(long.class, TypeUtil::parseLong);
                put(Long.class, TypeUtil::parseLong);
                put(float.class, TypeUtil::parseFloat);
                put(Float.class, TypeUtil::parseFloat);
                put(double.class, TypeUtil::parseDouble);
                put(Double.class, TypeUtil::parseDouble);
                put(char.class, TypeUtil::parseCharacter);
                put(Character.class, TypeUtil::parseCharacter);
                put(boolean.class, TypeUtil::parseBoolean);
                put(Boolean.class, TypeUtil::parseBoolean);

                put(String.class, TypeUtil::parseString);
                put(Date.class, TypeUtil::parseDate);
            }}
    );


    public static <T> T parse(Object o, Class<T> type) {
        Asserts.Null(type);
        TypeParser parser = typeToParser.get(type);
        Asserts.Null(parser, "类型：{}没有解析器", type);
        return (T) parser.parse(o);
    }

    public static String parseString(Object o) {
        if (o == null) return null;
        return o.toString();
    }

    public static Date parseDate(Object o) {
        if (o == null) return null;
        if (o instanceof Date) {
            return (Date) o;
        }
        if (o instanceof Number) {
            return new Date(((Number) o).longValue());
        }
        if (o instanceof CharSequence) {
            return TimeUtil.parseDate(o.toString());
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Boolean"));
    }

    public static Boolean parseBoolean(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return o.toString().equalsIgnoreCase("true");
        }
        if (o instanceof Number) {
            return ((Number) o).intValue() > 0;
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Boolean"));
    }

    public static Character parseCharacter(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            CharSequence sequence = (CharSequence) o;
            if (sequence.length() > 0) {
                throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Character"));
            }
            return sequence.charAt(0);
        }
        if (o instanceof Character) {
            return (Character) o;
        }
        if (o instanceof Number) {
            return (char) ((Number) o).intValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Character"));
    }

    public static Double parseDouble(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return Double.parseDouble(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).doubleValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Double"));
    }

    public static Float parseFloat(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return Float.parseFloat(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).floatValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Float"));
    }

    public static Long parseLong(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return Long.parseLong(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).longValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Long"));
    }

    public static Short parseShort(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return Short.parseShort(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).shortValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Short"));
    }

    public static Byte parseByte(Object o) {
        if (o == null) return null;
        if (o instanceof Byte) {
            return (Byte) o;
        }
        if (o instanceof CharSequence) {
            return Byte.parseByte(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).byteValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Byte"));
    }


    public static Integer parseInteger(Object o) {
        if (o == null) return null;
        if (o instanceof CharSequence) {
            return Integer.parseInt(o.toString());
        }
        if (o instanceof Number) {
            return ((Number) o).intValue();
        }
        throw new IllegalArgumentException(CommonUtil.format(parserErr, o, "Integer"));
    }


}
